home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacHack 2000
/
MacHack 2000.toast
/
pc
/
The Hacks
/
Softshoe
/
Lisa's Mac Parts
/
Windows
/
Window.cp
< prev
next >
Wrap
Text File
|
2000-06-23
|
8KB
|
358 lines
// Window.cp
#ifndef Window_h
#include "Window.h"
#endif
#ifndef WindowDefinition_h
#include "WindowDefinition.h"
#endif
#ifndef WindowUpdater_h
#include "WindowUpdater.h"
#endif
#ifndef MouseDownEvent_h
#include "MouseDownEvent.h"
#endif
#ifndef GraphicsDeviceObject_h
#include "GraphicsDeviceObject.h"
#endif
#ifndef MenuBar_h
#include "MenuBar.h"
#endif
#ifndef WindowInitializer_h
#include "WindowInitializer.h"
#endif
#ifndef Application_h
#include "Application.h"
#endif
#ifndef BroadcastLoop_h
#include "BroadcastLoop.h"
#endif
#ifndef WindowPile_h
#include "WindowPile.h"
#endif
#ifndef WindowLocation_h
#include "WindowLocation.h"
#endif
#ifndef CellClicker_h
#include "CellClicker.h"
#endif
#ifndef CellCursorCollector_h
#include "CellCursorCollector.h"
#endif
#ifndef CellUpdater_h
#include "CellUpdater.h"
#endif
#ifndef RegionObject_h
#include "RegionObject.h"
#endif
Window::Window( const WindowDefinition& theDefinition )
: WindowController( visibility, zoomed, bounds, name, index ),
Receiver<PreparingToQuit>( PreparingToQuit::TheBroadcaster() ),
definition( theDefinition ),
window( theDefinition.Procedure(), theDefinition.Closeable() ),
pane( window ),
registration( &window, this ),
closingLink( focus, *this ),
visibility( *this, &Window::GetVisibility, &Window::SetVisibility ),
zoomed( *this, &Window::GetZoomed, &Window::SetZoomed ),
bounds( *this, &Window::GetBounds, &Window::SetBounds ),
name( *this, &Window::GetName, &Window::SetName ),
index( *this, &Window::GetIndex, &Window::SetIndex ),
controlIdlers( window )
{
WindowLocator::Register( registration );
}
Window::~Window()
{
}
void Window::Initialize( const WindowInitializer& initializer )
{
SetName( initializer.NameFor( *this ) );
SetBounds( initializer.PositionFor( *this ) );
if ( initializer.VisibilityFor( *this ) )
{
if ( initializer.ZoomOpen() )
{
Rectangle destination = window.GlobalBounds();
destination.Outset( definition.FrameSize() );
ZoomRects( &initializer.ZoomSource(),
&destination,
8,
kZoomNoAcceleration );
}
SetIndex( initializer.IndexFor( *this ) );
}
}
void Window::Update()
{
WindowUpdater updater( window );
pane.Deliver( CellUpdater( window.VisibleRegion() ) );
}
void Window::Activate()
{
focus.BeFavored();
Assert( focus.Active() );
}
void Window::Deactivate()
{
focus.BeDisfavored();
Assert( !focus.Active() );
}
void Window::ClickContent( const MouseDownEvent& event )
{
pane.Deliver( CellClicker( event ) );
if ( event.Activating() )
index.Set( 1 );
}
void Window::ClickDrag( const MouseDownEvent& event )
{
if ( event.Activating() && !event.Command() )
index.Set( 1 );
window.MoveByDragging( event.GlobalPoint() );
bounds = bounds; // To help with recording
}
void Window::ClickClose( const MouseDownEvent& event )
{
if ( window.TrackCloseBox( event.GlobalPoint() ) )
Close();
}
void Window::ClickZoomIn( const MouseDownEvent& event )
{
if ( window.TrackZoomInBox( event.GlobalPoint() ) )
zoomed.Set( !GetZoomed() );
}
void Window::ClickZoomOut( const MouseDownEvent& event )
{
if ( window.TrackZoomOutBox( event.GlobalPoint() ) )
zoomed.Set( !GetZoomed() );
}
void Window::ClickGrow( const MouseDownEvent& event )
{
PointObject newSize = window.SizeByDragging( event.GlobalPoint(),
pane.MinimumSize(),
pane.MaximumSize() );
Rectangle newBounds( window.GlobalBounds() );
newBounds.SetBottomRight( newBounds.TopLeft() + newSize );
bounds.Set( newBounds );
}
const CursorObject& Window::Cursor( const MouseEvent& event,
RegionObject& sleep )
{
CellCursorCollector collector( event, sleep );
pane.Deliver( collector );
sleep += Port().LocalToGlobal();
return collector.Cursor();
}
bool Window::GetVisibility() const
{
return window.Visible();
}
void Window::SetVisibility( bool toShow )
{
if ( toShow )
window.Show();
else
window.Hide();
}
bool Window::GetZoomed() const
{
return window.GlobalBounds() == BestBounds();
}
void Window::SetZoomed( bool toZoom )
{
if ( toZoom )
{
window.SetStandardBounds( BestBounds() );
window.ZoomToStandardBounds();
}
else
window.ZoomToUserBounds();
pane.AnnounceSizeChange();
}
Rectangle Window::GetBounds() const
{
return window.GlobalBounds();
}
void Window::SetBounds( Rectangle newBounds )
{
window.SetBounds( newBounds );
pane.AnnounceSizeChange();
}
ConstPString Window::GetName() const
{
return nameString;
}
void Window::SetName( ConstPString newName )
{
nameString = newName;
window.SetTitle( newName );
}
uint32 Window::GetIndex() const
{
return window.Index();
}
void Window::SetIndex( uint32 newIndex )
{
window.SetIndex( newIndex );
}
GDHandle Window::DefaultScreen() const
{
::WindowObject *front = ::WindowObject::Front();
return front == 0
? GraphicsDeviceObject::Main()
: front->NearestScreen();
}
Rectangle Window::DefaultPosition( GDHandle screen ) const
{
Rectangle available( AvailableArea( screen ) );
PointObject bestSize = pane.BestSize( available.Size() );
PointObject reasonableSize = pane.ReasonableSize();
Rectangle bestPile;
uint32 bestPileScore = maxuint32;
for ( WindowPile pile( available, bestSize );
pile.Unfinished() && bestPileScore > 0;
pile++ )
{
uint32 score = WindowObject::CountVisibleWindows( *pile );
if ( score >= bestPileScore )
continue;
bestPileScore = score;
bestPile = *pile;
}
PointObject bestLocation;
uint32 bestLocationScore = maxuint32;
for ( WindowLocation location( bestPile, reasonableSize );
location.Unfinished() && bestLocationScore > 0;
location++ )
{
Rectangle nearby( *location, *location );
nearby.Outset( 5 );
uint32 score = WindowObject::CountVisibleWindows( nearby );
if ( score >= bestLocationScore )
continue;
bestLocationScore = score;
bestLocation = *location;
}
bestSize = pane.BestSize( available.BottomRight() - bestLocation );
return Rectangle( bestLocation, bestLocation + bestSize );
}
bool Window::CanClose() const
{
return definition.Closeable();
}
void Window::Close( SavingOption savingOption )
{
for ( BroadcastLoop<PreparingToClose> receiver( *this );
receiver.Unfinished();
receiver++ )
receiver->PrepareToClose( savingOption );
window.Hide();
focus.BeDisfavored();
delete this;
}
void Window::PrepareToQuit( SavingOption savingOption )
{
Close( savingOption );
}
GDHandle Window::BestScreen() const
{
return window.NearestScreen();
}
Rectangle Window::BestBounds() const
{
return BestBounds( BestScreen() );
}
Rectangle Window::BestBounds( GDHandle screen ) const
{
return BestBounds( AvailableArea( screen ) );
}
Rectangle Window::BestBounds( Rectangle available ) const
{
Rectangle best( window.GlobalBounds() );
PointObject bestSize = pane.BestSize( available.Size() );
best.right = best.left + bestSize.h;
best.bottom = best.top + bestSize.v;
if ( best.right > available.right )
best += PointObject( available.right - best.right, 0 );
if ( best.bottom > available.bottom )
best += PointObject( 0, available.bottom - best.bottom );
if ( best.left < available.left )
best += PointObject( available.left - best.left, 0 );
if ( best.top < available.top )
best += PointObject( 0, available.top - best.top );
return best;
}
Rectangle Window::AvailableArea( GDHandle theScreen ) const
{
GraphicsDeviceObject screen( theScreen );
Rectangle area( screen.Bounds() );
if ( screen.IsMainScreen() )
area.top += MenuBar::The().Height();
area.Inset( 3 );
area.Inset( window.FrameSize() );
return area;
}